/*
 * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.corba.se.impl.ior;


public class ByteBuffer {

  /**
   * The array buffer into which the components of the ByteBuffer are
   * stored. The capacity of the ByteBuffer is the length of this array buffer,
   * and is at least large enough to contain all the ByteBuffer's elements.<p>
   *
   * Any array elements following the last element in the ByteBuffer are 0.
   */
  protected byte elementData[];

  /**
   * The number of valid components in this <tt>ByteBuffer</tt> object.
   * Components <tt>elementData[0]</tt> through
   * <tt>elementData[elementCount-1]</tt> are the actual items.
   *
   * @serial
   */
  protected int elementCount;

  /**
   * The amount by which the capacity of the ByteBuffer is automatically
   * incremented when its size becomes greater than its capacity.  If
   * the capacity increment is less than or equal to zero, the capacity
   * of the ByteBuffer is doubled each time it needs to grow.
   *
   * @serial
   */
  protected int capacityIncrement;

  /**
   * Constructs an empty ByteBuffer with the specified initial capacity and
   * capacity increment.
   *
   * @param initialCapacity the initial capacity of the ByteBuffer.
   * @param capacityIncrement the amount by which the capacity is increased when the ByteBuffer
   * overflows.
   * @throws IllegalArgumentException if the specified initial capacity is negative
   */
  public ByteBuffer(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0) {
      throw new IllegalArgumentException("Illegal Capacity: " +
          initialCapacity);
    }
    this.elementData = new byte[initialCapacity];
    this.capacityIncrement = capacityIncrement;
  }

  /**
   * Constructs an empty ByteBuffer with the specified initial capacity and
   * with its capacity increment equal to zero.
   *
   * @param initialCapacity the initial capacity of the ByteBuffer.
   * @throws IllegalArgumentException if the specified initial capacity is negative
   */
  public ByteBuffer(int initialCapacity) {
    this(initialCapacity, 0);
  }

  /**
   * Constructs an empty ByteBuffer so that its internal data array
   * has size <tt>10</tt> and its standard capacity increment is
   * zero.
   */
  public ByteBuffer() {
    this(200);
  }

  /**
   * Trims the capacity of this ByteBuffer to be the ByteBuffer's current
   * size. If the capacity of this cector is larger than its current
   * size, then the capacity is changed to equal the size by replacing
   * its internal data array, kept in the field <tt>elementData</tt>,
   * with a smaller one. An application can use this operation to
   * minimize the storage of a ByteBuffer.
   */
  public void trimToSize() {
    int oldCapacity = elementData.length;
    if (elementCount < oldCapacity) {
      byte oldData[] = elementData;
      elementData = new byte[elementCount];
      System.arraycopy(oldData, 0, elementData, 0, elementCount);
    }
  }

  /**
   * This implements the unsynchronized semantics of ensureCapacity.
   * Synchronized methods in this class can internally call this
   * method for ensuring capacity without incurring the cost of an
   * extra synchronization.
   *
   * @see java.util.ByteBuffer#ensureCapacity(int)
   */
  private void ensureCapacityHelper(int minCapacity) {
    int oldCapacity = elementData.length;
    if (minCapacity > oldCapacity) {
      byte oldData[] = elementData;
      int newCapacity = (capacityIncrement > 0) ?
          (oldCapacity + capacityIncrement) : (oldCapacity * 2);
      if (newCapacity < minCapacity) {
        newCapacity = minCapacity;
      }
      elementData = new byte[newCapacity];
      System.arraycopy(oldData, 0, elementData, 0, elementCount);
    }
  }

  /**
   * Returns the current capacity of this ByteBuffer.
   *
   * @return the current capacity (the length of its internal data arary, kept in the field
   * <tt>elementData</tt> of this ByteBuffer.
   */
  public int capacity() {
    return elementData.length;
  }

  /**
   * Returns the number of components in this ByteBuffer.
   *
   * @return the number of components in this ByteBuffer.
   */
  public int size() {
    return elementCount;
  }

  /**
   * Tests if this ByteBuffer has no components.
   *
   * @return <code>true</code> if and only if this ByteBuffer has no components, that is, its size
   * is zero; <code>false</code> otherwise.
   */
  public boolean isEmpty() {
    return elementCount == 0;
  }

  public void append(byte value) {
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = value;
  }

  public void append(int value) {
    ensureCapacityHelper(elementCount + 4);
    doAppend(value);
  }

  private void doAppend(int value) {
    int current = value;
    for (int ctr = 0; ctr < 4; ctr++) {
      elementData[elementCount + ctr] = (byte) (current & 255);
      current = current >> 8;
    }
    elementCount += 4;
  }

  public void append(String value) {
    byte[] data = value.getBytes();
    ensureCapacityHelper(elementCount + data.length + 4);
    doAppend(data.length);
    System.arraycopy(data, 0, elementData, elementCount, data.length);
    elementCount += data.length;
  }

  /**
   * Returns an array containing all of the elements in this ByteBuffer
   * in the correct order.
   *
   * @since 1.2
   */
  public byte[] toArray() {
    return elementData;
  }
}
